﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

using SMBL.Interface.LifeCycle;
using SMBL.Global;
using SMBL.ConfigElement.DBProvider;
using SMBL.ConfigElement.FileLocate;
using SMBL.ConfigElement.PageLocate;

namespace SMBL
{
    namespace Core
    {
        public class Kernel : IStart, IEnd
        {
            ///
            //////////////////////////////////////////////////////////////////////////
            // Only Instance of the Website Core
            private static Kernel instanceCore;
            //////////////////////////////////////////////////////////////////////////

            //////////////////////////////////////////////////////////////////////////
            // Parameters
            //////////////////////////////////////////////////////////////////////////

            //public List<DBProviderInfo> ProviderInfoList;
            public Hashtable ProviderInfoList = new Hashtable();
            //public List<ConnectString> ConnectStringList;
            public Hashtable ConnectStringList = new Hashtable();
            //public List<FileLocation> FileLocateList;
            public Hashtable FileLocateList = new Hashtable();
            //public List<PageLocate> PageLocateList;
            public Hashtable PageLocateList = new Hashtable();

            /// <summary>
            /// Initialize the Core
            /// Create the only instance of the core
            /// @Author: Push
            /// </summary>
            public static void Initialize()
            {
                // Create the instance
                if (Kernel.instanceCore == null)
                    Kernel.instanceCore = new Kernel();

                // Start the core
                Kernel.instanceCore.Start();
            }

            /// <summary>
            /// Get the only instance of the Core
            /// @Author: Push
            /// </summary>
            /// <returns></returns>
            public static Kernel GetInstance()
            {
                if (Kernel.instanceCore == null)
                    Kernel.Initialize();
                // return the only instance
                return Kernel.instanceCore;
            }

            //////////////////////////////////////////////////////////////////////////
            // Interface
            //////////////////////////////////////////////////////////////////////////

            /// <summary>
            /// End the core
            /// @Author: Push
            /// </summary>
            /// <returns>Statue of the process</returns>
            #region IEnd Members

            public bool End()
            {
                //throw new NotImplementedException();

                // Release the resource
                instanceCore.ProviderInfoList.Clear();
                instanceCore.ConnectStringList.Clear();
                instanceCore.FileLocateList.Clear();
                instanceCore.PageLocateList.Clear();

                // End Log System
                LogSystem.Terminate();
                // End Error System
                ErrorSystem.Terminate();
                return true;
            }

            #endregion

            /// <summary>
            /// Start the core
            /// @Author: Push
            /// </summary>
            /// <returns>Statue of the process</returns>
            #region IStart Members

            public bool Start()
            {
                //throw new NotImplementedException();

                System.Xml.XmlNodeList xmlElements = WebSite.ConfigXML.DocumentElement.ChildNodes;
                for (Int32 i = xmlElements.Count - 1; i >= 0; --i)
                {
                    switch (xmlElements[i].Name)
                    {
                        // DBProvider
                        case "DBProvider":
                            this.getProviderElement(xmlElements[i]);
                            break;
                        // ConnectString
                        case "ConnectString":
                            this.getConnectStringElement(xmlElements[i]);
                            break;
                        // FileLocate
                        case "FileLocate":
                            this.getFileLocateElement(xmlElements[i]);
                            break;
                        // Page
                        case "Page":
                            this.getPageLocateElement(xmlElements[i]);
                            break;
                        default: break;
                    }
                }

                // Start Error System
                // Get Error File Locate
                FileLocation errorFileLocation = (FileLocation)FileLocateList["Error"];
                // If failed to get the file location
                // Create a new one
                if (errorFileLocation == null)
                {
                    errorFileLocation = new FileLocation();
                    errorFileLocation.Title = "Error";
                    errorFileLocation.Path = WebSite.SysPath + "Error.xml";
                    errorFileLocation.MaxSize = 1000;
                    errorFileLocation.MaxCacheSize = 10;

                    FileLocateList.Add("Error", errorFileLocation);
                    //FileLocateList.Add(errorFileLocation);
                }
                ErrorSystem.Initialize(errorFileLocation);
                // Start Log System
                // Get Log File Locate
                FileLocation logFileLocation = (FileLocation)FileLocateList["Log"];
                // If failed to find the location
                // Create a new one
                if (logFileLocation == null)
                {
                    logFileLocation = new FileLocation();
                    logFileLocation.Title = "Log";
                    logFileLocation.Path = WebSite.SysPath + "Log.xml";
                    logFileLocation.MaxSize = 2000;
                    logFileLocation.MaxCacheSize = 10;

                    FileLocateList.Add("Log", logFileLocation);
                }
                LogSystem.Initialize(logFileLocation);
                return true;
            }

            #endregion

            //////////////////////////////////////////////////////////////////////////
            // Method
            //////////////////////////////////////////////////////////////////////////

            /// <summary>
            /// @Author: Push
            /// </summary>
            /// <param name="elementNode"></param>
            private void getProviderElement(System.Xml.XmlNode elementNode)
            {
                DBProviderInfo providerInfo = new DBProviderInfo();
                // Name
                providerInfo.Name = elementNode.Attributes["Name"].InnerText;
                // Type
                //providerInfo.TYPE = (ProviderType)elementNode.Attributes["TYPE"].InnerText;
                providerInfo.TYPE = ConvertToType.Convert(
                    elementNode.Attributes["TYPE"].InnerText);
                // MaxConn
                providerInfo.MaxConn = Convert.ToInt64(elementNode.Attributes["MaxConn"].InnerText);
                // Child Nodes
                // The nodes must appear in order
                System.Xml.XmlNodeList innerNodes = elementNode.ChildNodes;
                // DBName
                providerInfo.DBName = innerNodes[0].InnerText;
                // DBPath
                providerInfo.DBPath = innerNodes[1].InnerText;
                // Username
                providerInfo.UserName = innerNodes[2].InnerText;
                // Password
                providerInfo.Password = innerNodes[3].InnerText;

                // Add to the list
                this.ProviderInfoList.Add(providerInfo.Name, providerInfo);
            }

            private void getConnectStringElement(System.Xml.XmlNode elementNode)
            {
                ConnectString connString = new ConnectString();
                // TYPE
                connString.TYPE = ConvertToType.Convert(
                    elementNode.Attributes["TYPE"].InnerText);

                // The String
                connString.InnerText = elementNode.InnerText;

                // Add to the list
                this.ConnectStringList.Add(connString.TYPE, connString);
            }

            private void getFileLocateElement(System.Xml.XmlNode elementNode)
            {
                FileLocation fileLocation = new FileLocation();
                // Max size
                fileLocation.MaxSize = Convert.ToInt64(elementNode.Attributes["MaxSize"].InnerText);
                // Max Cache size
                fileLocation.MaxCacheSize = Convert.ToInt32(elementNode.Attributes["MaxCacheSize"].InnerText);
                // Inner Nodes
                System.Xml.XmlNodeList innerNodes = elementNode.ChildNodes;
                // Title
                fileLocation.Title = innerNodes[0].InnerText;
                // Path
                fileLocation.Path = WebSite.AppPath + innerNodes[1].InnerText;

                // Add to the list
                this.FileLocateList.Add(fileLocation.Title, fileLocation);
            }

            private void getPageLocateElement(System.Xml.XmlNode elementNode)
            {
                PageLocate pageLocate = new PageLocate();
                // Code
                pageLocate.Code = elementNode.Attributes["Code"].InnerText;
                // Path
                pageLocate.Path = elementNode.ChildNodes[0].InnerText;

                // Add to the list
                this.PageLocateList.Add(pageLocate.Code, pageLocate);
            }
        }
    }
}